/******************************************************************************/
/*                                                                            */
/*  Copyright (c) 2009: ngi-central.org                                       */
/*  All rights reserved.                                                      */
/*                                                                            */
/******************************************************************************/


#ifndef __sgl_conditions_h__
#define __sgl_conditions_h__

#include <sgl/global_settings.h>
#include <sgl/exceptions.h>


// Some macro wizardry I've seen somewhere but can't remember where. This is
// needed to get the file name and line number into the exception string.
#define STRINGIZE(L) #L 
#define MAKESTRING(M, L) M(L) 
#define LINE MAKESTRING(STRINGIZE, __LINE__) 
#define LOCATION __FILE__ "(" LINE ") : "


/******************************************************************************/
/*                                                                            */
/* SGL_PRECONDITION                                                           */
/*                                                                            */
/******************************************************************************/

/// Macro to check precondition violations.
//!
//! In SGL, a precondition is a condition or predicate that must always be true 
//!	prior to the execution of some section of code. If a precondition is 
//! violated, the effect of the section of code becomes undefined and thus may 
//! or may not work as intended.
//! 
//! SGL checks preconditions with the SGL_PRECONDITION macro, which - when 
//! defined - throws the precondition_violated exception when the precondition 
//! is not true.
//!
//! The user of SGL can inhibit this behavior by defining the 
//! SGL_PRECONDITION(condition, message) macro as an empty macro before the 
//! inclusion of any SGL header file. 
#ifndef SGL_PRECONDITION
	#define SGL_PRECONDITION(condition, message)                               \
		if (!(condition))                                                      \
			throw sgl::precondition_violated(                                  \
				"precondition <<" #condition ">> violated in file: "           \
					LOCATION #message);
#endif

/******************************************************************************/
/*                                                                            */
/* SGL_POSTCONDITION                                                          */
/*                                                                            */
/******************************************************************************/

/// Macro to check postcondition violations.
//!
//! In SGL, a postcondition is a condition or predicate that must always be true 
//! after the execution of some section of code. 
//! 
//! SGL checks postconditions with the SGL_POSTCONDITION macro, which - when 
//! defined - throws the postcondition_violated exception when the postcondition 
//! is not true.
//!
//! The user of SGL can inhibit this behavior by defining the 
//! SGL_POSTCONDITION(condition, message) macro as an empty macro before the 
//! inclusion of any SGL header file. 
#ifndef SGL_POSTCONDITION
	#define SGL_POSTCONDITION(condition, message)                              \
		if (!(condition))                                                      \
			throw sgl::postcondition_violated(                                 \
				"postcondition <<" #condition ">> violated in file: "          \
				LOCATION #message);
#endif

/******************************************************************************/
/*                                                                            */
/* SGL_INVARIANT                                                              */
/*                                                                            */
/******************************************************************************/

/// Macro to check invariant violations.
//!
//! In SGL, an invariant is a predicate that is supposed to remain true 
//! throughout the whole lifetime of a class.
//! 
//! SGL checks invariants with the SGL_INVARIANT macro, which - when defined -
//! throws the invariant_violated exception when the invariant is not true.
//!
//! The user of SGL can inhibit this behavior by defining the 
//! SGL_INVARIANT(condition, message) macro as an empty macro before the 
//! inclusion of any SGL header file. 
#ifndef SGL_INVARIANT
	#define SGL_INVARIANT(condition, message)                                  \
		if (!(condition))                                                      \
			throw sgl::invariant_violated(                                     \
				"invariant <<" #condition ">> violated in file: "              \
				LOCATION #message);
#endif


#endif // __sgl_conditions_h__
